package com.asiainfo.simpledao;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

public class Row extends HashMap<String, Object> {

	private static final long serialVersionUID = 9178606903603606031L;

	private final Map<String, String> lowerCaseMap = new HashMap<String, String>();

	@Override
	public boolean containsKey(Object key) {
		Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH));
		return super.containsKey(realKey);
	}

	@Override
	public Object get(Object key) {
		Object realKey = lowerCaseMap.get(key.toString().toLowerCase(Locale.ENGLISH));
		return super.get(realKey);
	}

	@Override
	public Set<String> keySet() {
		return lowerCaseMap.keySet();
	}

	@Override
	public Object put(String key, Object value) {
		// 保持map和lowerCaseMap同步 在put新值之前remove旧的映射关系
		Object oldKey = lowerCaseMap.put(key.toLowerCase(Locale.ENGLISH), key);
		Object oldValue = super.remove(oldKey);
		super.put(key, value);
		return oldValue;
	}

	@Override
	public void putAll(Map<? extends String, ?> m) {
		for (Map.Entry<? extends String, ?> entry : m.entrySet()) {
			String key = entry.getKey();
			Object value = entry.getValue();
			this.put(key, value);
		}
	}

	@Override
	public Object remove(Object key) {
		Object realKey = lowerCaseMap.remove(key.toString().toLowerCase(Locale.ENGLISH));
		return super.remove(realKey);
	}

	public String getString(String name) {
		Object value = get(name);
		return value == null ? null : value.toString();
	}

	public Object get(Object name, Object def) {
		Object value = get(name);
		return value == null ? def : value;
	}

	public String getString(String name, String defaultValue) {
		return get(name, defaultValue).toString();
	}

	public Integer getInteger(String name) {
		return getInteger(name, null);
	}

	public Integer getInteger(String name, Integer defaultValue) {
		String value = getString(name, "");
		return "".equals(value) ? defaultValue : Integer.parseInt(value);
	}

	public Long getLong(String name) {
		return getLong(name, null);
	}

	public Long getLong(String name, Long defaultValue) {
		String value = getString(name, "");
		return "".equals(value) ? defaultValue : Long.parseLong(value);
	}

	public Float getFloat(String name) {
		return getFloat(name, null);
	}

	public Float getFloat(String name, Float defaultValue) {
		String value = getString(name, "");
		return "".equals(value) ? defaultValue : Float.parseFloat(value);
	}

	public Double getDouble(String name) {
		return getDouble(name, null);
	}

	public Double getDouble(String name, Double defaultValue) {
		String value = getString(name, "");
		return "".equals(value) ? defaultValue : Double.parseDouble(value);
	}

	public BigDecimal getBigDecimal(String name) {
		return getBigDecimal(name, null);
	}

	public BigDecimal getBigDecimal(String name, BigDecimal defaultValue) {
		String value = getString(name, "");
		return "".equals(value) ? defaultValue : new BigDecimal(value);
	}

	public Boolean getBoolean(String name) {
		return getBoolean(name, null);
	}

	public Boolean getBoolean(String name, Boolean defaultValue) {
		String value = getString(name, "");
		return "".equals(value) ? defaultValue : Boolean.valueOf(value);
	}

	public Date getDate(String name, String format) {
		return getDate(name, format, null);
	}

	public Date getDate(String name, String format, Date defaultValue) {
		if (format == null || "".equals(format)) {
			return defaultValue;
		}

		String timeStr = getString(name, "");
		if ("".equals(timeStr))
			return defaultValue;

		Date date = null;
		if (format.length() != timeStr.length())
			format = getTimestampFormat(timeStr);
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		try {
			date = new Timestamp(sdf.parse(timeStr).getTime());
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
		return date;
	}

	private String getTimestampFormat(String value) {
		switch (value.length()) {
		case 4:
			return "yyyy";
		case 6:
			return "yyyyMM";
		case 7:
			return "yyyy-MM";
		case 8:
			return "yyyyMMdd";
		case 10:
			return "yyyy-MM-dd";
		case 13:
			return "yyyy-MM-dd HH";
		case 16:
			return "yyyy-MM-dd HH:mm";
		case 19:
			return "yyyy-MM-dd HH:mm:ss";
		case 21:
			return "yyyy-MM-dd HH:mm:ss.S";
		}
		return null;
	}

}
